/**
*******************************************************
*@file  celect.c
*@brief celect.c
*@author 花满楼
*@date     2020-7-2
*@version  V1
*@attention none
*******************************************************
*/
#include "rs485.h"
#include "can.h"
#include "protect.h"

#ifndef CELL_NUM
    #define CELL_NUM 54     //项目中有54个电芯
#endif

#ifndef CELL_PER_NUM
    #define CELL_PER_NUM 16     //项目中单个采集芯片采集电芯数量
#endif

#ifndef TEMP_PER_NUM
    #define TEMP_PER_NUM 2      //项目中单个采集芯片采集温度数量
#endif

#define MAX(x,y)   ((x)<(y) ? (y) : (x))  /**<取大值的宏定义*/
#define MIN(x,y)   ((x)<(y) ? (x) : (y))  /**<取小值的宏定义*/

u8 cell_id_hex[20] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}; /**<电芯的ID*/

/**
*******************************************************
*@brief 处理上传上位机的数组
*@param   none
*@return  none
*@note    通讯协议中的模拟量可能不是C语言意义上的模拟量，后期调试注意定义
*******************************************************
*/
void Collect()
{
    u16 i;
    u16 average_vol, average_temp;
    u16 total_vol = 0, total_temp = 0;
    u8 cell_id_ascii[20];

    if (Flag_ParaChange_485 == 0)   //有参数写入时不更新，防止覆盖
    {
        /************电压平均值的求取***********/
        for (i = 0; i < 15; i++) /*15个结构体，一个存储4个电压*/
        {
            total_vol += Cell_Vol_Data[i].Cell_1 + Cell_Vol_Data[i].Cell_2 + Cell_Vol_Data[i].Cell_3 + Cell_Vol_Data[i].Cell_4;
        }

        average_vol = total_vol / CELL_NUM;
        total_vol = 0;

        /************温度平均值的求取***********/
        for (i = 0; i < 3; i++) /*3个结构体，一个存储4个温度*/
        {
            total_temp += Cell_Temper_Data[i].Temp_1 + Cell_Temper_Data[i].Temp_2 + Cell_Temper_Data[i].Temp_3 + Cell_Temper_Data[i].Temp_4;
        }

        average_temp = total_temp / (TEMP_PER_NUM * 5); /*5组*/
        total_temp = 0;
        /***************模拟量**************/
        Analog_Data[0] =    Pack_Addr;//从机地址，0x16-0x25
        Analog_Data[1] =    TERNARY;//电池类型，1三元，2铁锂，3钴酸，4锰酸，5钛酸
        Analog_Data[2] =    Pack_Mes_Tol.Pack_Vol;//电池总压 0.1V
        Analog_Data[3] =    Pack_Mes_Tol.Pack_Cur + 30000;//电池电流，0.1A，偏移量30000.充电为正，放电为负 * 10 + 30000
        Analog_Data[4] =    Pack_Mes_Tol.Pack_SOC;//SOC 1%
        Analog_Data[5] =    CELL_Vol_Maxi.Max_Cell_Volt;//最高单体电压 1mV.
        Analog_Data[6] =    CELL_Vol_Maxi.Min_Cell_Volt;//最低单体电压    1mV
        Analog_Data[7] =    Pack_Tem_Maxi.Max_Cell_Tem + 40;//最高单体温度 1℃，偏移量40
        Analog_Data[8] =    Pack_Tem_Maxi.Min_Cell_Tem + 40;//最低单体温度 1℃，偏移量40
        Analog_Data[9] =    average_vol;//平均单体电压    1mV
        Analog_Data[10] =   average_temp + 40;  //平均单体温度 1℃，偏移量40
        Analog_Data[11] =   0xFF00; //固件版本 1，高8位固定为1，第8位固定为0
        Analog_Data[12] =   RATED_CAPACITY; //电池额定容量    0.1Ah
        Analog_Data[13] =   Pack_Mes_Tol.Pack_SOH;  //SOH 1%
        Analog_Data[14] =   0xAA55; //软件版本 60101（十进制），万位表示高度（U），千、百位表示正式版本号，
        //剩余两位表示测试版本号，01指第一版升级正式版，测试版本号应为00
        Analog_Data[15] =   0x00;   //并机在线台数
        Analog_Data[16] = (Pack_Rly_Status.RlyStr.Bit.ChaRlyStr | (Pack_Rly_Status.RlyStr.Bit.DisRlyStr >> 1) |
                           (Pack_Rly_Status.RlyStr.Bit.PreRlyStr >> 2)) & 0x0007; //继电器状态，bit0充电，bit1放电，bit2预充；0断开，1闭合

        for (i = 0; i < CELL_PER_NUM; i++)
        {
            Analog_Data[20 + i] =     	Cell_Vol_Data[i].Cell_1;  //单体电压，1mV，0xffff表示无效
            Analog_Data[20 + 16 + i] =  Cell_Vol_Data[i].Cell_2; //单体电压，1mV，0xffff表示无效
            Analog_Data[20 + 32 + i] =  Cell_Vol_Data[i].Cell_3; //单体电压，1mV，0xffff表示无效
            Analog_Data[20 + 48 + i] =  Cell_Vol_Data[i].Cell_4; //单体电压，1mV，0xffff表示无效
        }

        for (i = 0; i < 75 - CELL_NUM; i++) //75是协议中的最大电芯数量，无效位按照0xffff发送
        {
            Analog_Data[20 + CELL_NUM + i]  =   0xffff;
        }

        for (i = 0; i < TEMP_PER_NUM; i++)
        {
            Analog_Data[95 + i] 	=   Cell_Temper_Data[i].Temp_1; //单体温度，1℃，偏移量40
            Analog_Data[95 + 2 + i] =   Cell_Temper_Data[i].Temp_2; //单体温度，1℃，偏移量40
            Analog_Data[95 + 4 + i] =   Cell_Temper_Data[i].Temp_3; //单体温度，1℃，偏移量40
            Analog_Data[95 + 6 + i] =   Cell_Temper_Data[i].Temp_4; //单体温度，1℃，偏移量40
        }

        for (i = 0; i < 25 - TEMP_PER_NUM * 4; i++) //无效位按照0xffff发送
        {
            Analog_Data[95 + TEMP_PER_NUM * 4 + i] = 0xffff;
        }

        HextoASCII(cell_id_hex, cell_id_ascii, 10); //把序列号转换成阿斯克码

        /***************设置量**************/
        /*
            *序列号：每个产品特有的20位ASCII编码。
            比如，序列号为1234657890123456789A，发送时会以ASCII码的十六进制进行发送，该序列号会按照以下形式发送：
            0x31 0x32 0x33 0x34 0x36 0x35 0x37 0x38 0x39 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x41
            *序列号暂无定义规则，应该由锂电池厂家提供
        */
        for (i = 0; i < 10; i++)
        {
            Set_Dress[i] = cell_id_ascii[2 * i + 1] + cell_id_ascii[2 * i];
        }

        /***************告警量**************/
        Alarm_Data[0] = Alarm_Reg.Slight_Alarm1.Word;      	 	//轻微故障1
        Alarm_Data[1] = Alarm_Reg.Slight_Alarm2.Word;       	//轻微故障2
        Alarm_Data[2] = Alarm_Reg.Serious_Alarm1.Word;      	//严重故障1
        Alarm_Data[3] = Alarm_Reg.Serious_Alarm2.Word & 0x07FF; //严重故障2.高9位是自定义故障，不通过协议上传到UPS
        /***************控制量**************/
        Control_Date[0] = Control_Reg.Control1.Word;        //控制量1
        Control_Date[1] = Control_Reg.Control2.Word;        //控制量2
        Control_Date[2] = Control_Reg.Control3.Word;        //控制量3
        Control_Date[3] = Control_Reg.Control4.Word;        //控制量4
    }
}
/************************************************************************
*   File name: HextoASCII()；
*   Description: 16位数值转换为对应的ASCII的值，用于485通讯
*   输入：Origin：待转换的数组；Lenth：数据长度
*   输出：Target：转换完成的数组
*-----------------------------------------------------------------------*/
void HextoASCII(u8 *Origin, u8 *Target, u16 Lenth)
{
    u8 i;

    for (i = 0; i < Lenth; i++)
    {
        if ((*Origin & 0xF0) < 0xA0)
        {
            *Target = (*Origin & 0x0F) + 0x30;
        }
        else
            *Target = (*Origin & 0x0F) + 0x37;

        Target++;

        if ((*Origin & 0x0F) < 0x0A)
        {
            *Target = ((*Origin & 0xF0) >> 4) + 0x30;
        }
        else
            *Target = ((*Origin & 0xF0) >> 4) + 0x37;

        Target++;
        Origin++;
    }
}
/************************************************************************
*	File name: ASCIItoHex()；
*	Description: ASCII转换成对应的16位数值，用于485通讯
*	输入：Origin：待转换的数组；Lenth：数据长度
*	输出：Target：转换完成的数组
*-----------------------------------------------------------------------*/
void ASCIItoHex(u8 *Origin,u8 *Target,u8 Lenth)
{
    u8 i;
    for(i=0; i<Lenth; i++)
    {
        if(*Origin<0x40)
        {
            *Target = *Origin<<4;
        }
        else
            *Target = (*Origin<<4) + 0x90;

        Origin++;

        if(*Origin<0x40)
        {
            *Target |= *Origin&0x0F;
        }
        else
            *Target |= (*Origin&0x0F) + 0x09;

        Target++;
        Origin++;
    }
}
